﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace Xnlab.Filio
{
    class Tester
    {
        internal Tester(KeyValuePair<string, string> FullIndexProviders, List<KeyValuePair<string, object>> WorkProviders)
        {
            WorkSettings.Initialize(FullIndexProviders, CompressionMethods.GZip, null, true, true, 5, WorkProviders, null, OnStorageBeforeFileProcess);
        }

        internal void Run(string Mode)
        {
            if (Mode.ToLower() == "server")
            {
                BaseManager manager = new WorkV7HTTPManager();//you can use WorkV7TCPManager
                Role role = new Role("user");
                role.AddFilePath(@"C:\Downloads\房子 - 副本");
                role.AddUser(new UserAuth("user", "pass"));
                role.AddRight(UserRights.Discover);
                role.AddRight(UserRights.Search);
                role.AddRight(UserRights.Delete);
                manager.Roles.AddRole(role);
                manager.Progress += new EventHandler<ProgressEventArgs>(OnWorkProgress);
                manager.Request += new EventHandler<DataTransferEventArgs>(OnManagerRequest);
                manager.Start(8880);
            }
            else
            {
                //you should restart computer before testing next work,
                //because windows caches(pre-fetchs) file while we use MD5CryptoServiceProvider to hash a file.
                //that is, test a single work test for one windows startup
                BaseWork workv7 = new WorkV7();
                Test(workv7);

                //Test(new Workv5());
                //Test(new WorkV4());
                //Test(new WorkV3());
                //Test(new WorkV2());
                //Test(new WorkV1());
            }

            Console.WriteLine();
            AddLog("all done");
            Console.Read();
        }

        private void OnManagerRequest(object sender, DataTransferEventArgs e)
        {
            //you can cancel request or shutdown listener here
        }

        private void OnStorageBeforeFileProcess(object sender, FileProcessEventArgs e)
        {
            //you can cancel file process or decrease cpu throttle here
        }

        private void Test(BaseWork Worker)
        {
            MatchTypes matchTypes = MatchTypes.InfoSame;//change to your option

            Stopwatch watch = new Stopwatch();
            //string matchFolder = @"C:\TestData\temp";//change to your folder
            //string targetFolder = @"C:\TestData\Data_Archive_2008_09";//change to your folder            
            FileURI remoteFolder = new FileURI(@"http://192.168.1.2:8880/C:\Downloads\房子 - 副本", "user", "pass", 0, null);//change to your folder
            string matchFolder = @"C:\temp";//change to your folder
            string targetFolder = @"C:\Downloads\房子";//change to your folder            
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            //parameters.Add(BaseWorkProvider.ParameterEncoding, Encoding.ASCII);
            //FileURI remoteFolder = new FileURI(@"ftp://ftp.globalscape.com/pub/cuteftppro", "", "", 0, parameters);//change to your folder
            //FileURI remoteFolder = new FileURI(@"ftp://localhost", "anonymous", "", 0, parameters);//change to your folder

            AddLog("Method:" + Worker.ToString());
            AddLog("Start:" + DateTime.Now);
            watch.Start();
            Dictionary<string, MatchFileItem> result;
            Worker.Progress += new EventHandler<ProgressEventArgs>(OnWorkProgress);
            FileURI[] filePaths = new FileURI[] { new FileURI(matchFolder), new FileURI(targetFolder), remoteFolder };
            result = Worker.Find(filePaths, new string[] { }, "Flat", SearchTypes.Name, matchTypes, HashMethods.Block);
            List<BasicFileInfo> matchFiles = Worker.FindAll(matchTypes, result, matchFolder);
            watch.Stop();
            AddLog("Elapsed:" + watch.Elapsed.ToString());
            AddLog("Dups:" + matchFiles.Count);
            foreach (BasicFileInfo item in matchFiles)
            {
                Console.WriteLine(item.FileName);
            }

            Console.WriteLine();
            switch (matchTypes)
            {
                case MatchTypes.ContentSame:
                    if (matchFiles.Count > 0)
                    {
                        Console.WriteLine("Delete duplicated files? input YES to procceed");
                        string confrim = Console.ReadLine().ToLower();
                        if (confrim == "yes")
                        {
                            List<BasicFileInfo> deletedFiles = Worker.DeleteAll(matchFiles, filePaths);
                            AddLog("deleted:" + deletedFiles.Count);
                            foreach (BasicFileInfo item in deletedFiles)
                            {
                                Console.WriteLine(item.FileName);
                            }
                        }
                    }
                    else
                        Console.WriteLine("no duplicate files");
                    break;
                case MatchTypes.ContentContains:
                    break;
                case MatchTypes.ContentExtract:
                    break;
                default:
                    break;
            }

            Console.WriteLine();
            Console.WriteLine();
        }

        private void AddLog(string Log)
        {
            //WorkUtils.AddVerbose(Log);
            Console.WriteLine(Log);
        }

        private void OnWorkProgress(object sender, ProgressEventArgs e)
        {
#if (VERBOSE)
            switch (e.ProgressType)
            {
                case WorkProgressTypes.FileFound:
                    Console.WriteLine("found match:");
                    Console.WriteLine("\tkey:" + e.Status.Key);
                    //Console.WriteLine("\toriginal:" + e.Status.Value.OriginalFile);
                    Console.WriteLine("\tmatch:" + e.Status.Value[e.Status.Value.Count - 1].FileName);
                    Console.WriteLine();
                    break;
                case WorkProgressTypes.FileAccess:
                case WorkProgressTypes.Network:
                    AddLog(e.Log);
                    break;
                case WorkProgressTypes.Detail:
                    Console.WriteLine(e.Log);
                    break;
                default:
                    break;
            }
            Console.WriteLine();
#endif
        }
    }

}